﻿using System;

namespace Jet.Dal
{
	/// <summary>
	/// Repository which supports change tracking of entities
	/// </summary>
	/// <typeparam name="TKey">Type of entity key</typeparam>
	/// <typeparam name="TEntity">Type of entity</typeparam>
	public interface IChangeTracking<in TKey, TEntity> where TEntity:class 
	{
		/// <summary>
		/// Attach an entity
		/// <exception cref="ArgumentNullException">If entity is null</exception>
		/// <exception cref="ArgumentOutOfRangeException">If entity state is unknown</exception>
		/// </summary>
		void Attach(TEntity entity);

		/// <summary>
		/// Returns state of the entity
		/// </summary>
		EntityState GetState(TEntity entity);

		/// <summary>
		/// Determines, if object with given key already attached to repository 
		/// and retrieve it if possible. Note, that only retrieved objects are processed.
		/// So if this function returns false, you can safelly attach detached object or use 
		/// returned one to perform operations.
		/// </summary>
		/// <param name="key">Key, value returned by CreateKey function</param>
		/// <param name="attachedObject">Attached object with key, equal to detachedObject</param>
		/// <returns>True if there is attached object with given key, false, otherwise</returns>
		bool TryGetAttachedObjectByKey(TKey key, out TEntity attachedObject);

		/// <summary>
		/// Detach an entity.
		/// </summary>
		/// <param name="entity"></param>
		/// <exception cref="ArgumentNullException">If entity is null</exception>
		void Detach(TEntity entity);
	}
}
